home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 1.iso / dist / fw_exmh.idb / usr / freeware / lib / exmh-2.5 / flist.tcl.z / flist.tcl
Text File  |  2002-07-08  |  18KB  |  664 lines

  1. #
  2. # flist.tcl
  3. #
  4. # Manage the folder list.
  5. # For folder display (fdisp.tcl):
  6. #    What folders have nested folders under them
  7. #    What folders have unseen messages
  8. # For scan listing (ftoc.tcl):
  9. #    What messages are unread.
  10. #
  11. # Some of the routines here are set up to run in a background interpreter.
  12. # When you see calls to BgRPC it is invoking the routine in the
  13. # forground UI interpreter, whether or not the current routine
  14. # is already running there.
  15. #
  16. # Copyright (c) 1993 Xerox Corporation.
  17. # Use and copying of this software and preparation of derivative works based
  18. # upon this software are permitted. Any distribution of this software or
  19. # derivative works must comply with all applicable United States export
  20. # control laws. This software is made available AS IS, and Xerox Corporation
  21. # makes no warranty about the software, its performance or its conformity to
  22. # any specification.
  23.  
  24.  
  25. proc Flist_Init {} {
  26.     global flist
  27.     FlistResetVars        ;# Reset unseen msgs state
  28.     set flist(context) {}
  29.     set flist(contextMtime) 0
  30.     set flist(cacheFileMtime) 0
  31.     Flist_FindAllFolders
  32. }
  33. proc FlistResetVars {} {
  34.     global flist
  35.     set flist(unseen) {}    ;# Sequence of folders to visit
  36.     set flist(unvisited) {}    ;# Unseen folders not yet visited
  37.     Exmh_Debug FlistResetVars
  38.     set flist(unvisitedNext) {}    ;# Temporary copy (next iteration)
  39.     set flist(newMsgs) 0    ;# Total count of unseen messages
  40.  
  41.     # flist(new,$folder)    is the number of unseen in a folder
  42.     #                (Update with care; 'trace'd by UnseenWinTrace)
  43.     # flist(newseq,$folder)    is the message id's of unseen messages
  44.     # flist(mtime,$folder)    is modify time of .mh_sequences file
  45.     foreach x [array names flist] {
  46.     if [regexp {^(new|newseq|mtime),} $x] {
  47.         # reset per-folder new and newseq state
  48.         unset flist($x)
  49.     }
  50.     }
  51.     if ![info exists flist(debug)] {
  52.     set flist(debug) 0
  53.     }
  54.     if {$flist(debug)} {
  55.     trace variable flist(newMsgs) w FlistTraceNewMsgs
  56.     trace variable flist(unseen) w FlistTraceUnseen
  57.     trace variable flist(unvisited) w FlistTraceUnvisited
  58.     set flist(listbox) .flistbox
  59.     set f $flist(listbox)
  60.     if ![winfo exists $f] {
  61.         Exwin_Toplevel $f "Flist Debug" Flist
  62.         Widget_Label $f newMsgs {top fillx } -textvariable flist(newMsgs)
  63.         Widget_Frame $f top Labels
  64.         Widget_Label $f.top unseen {left fill expand} -text Unseen
  65.         Widget_Label $f.top unvisited {left fill expand} -text Unvisited
  66.         FontWidget listbox $f.unseen
  67.         FontWidget listbox $f.unvisited
  68.         pack $f.unseen $f.unvisited -side left -fill both -expand true
  69.     }
  70.     }
  71. }
  72. proc FlistTraceNewMsgs {args} {
  73.     global flist
  74.     set l [info level]
  75.     incr l -1
  76.     Exmh_Debug flist(newMsgs) => $flist(newMsgs) : [info level $l] $args
  77. }
  78. proc FlistTraceUnseen {args} {
  79.     global flist
  80.     $flist(listbox).unseen delete 0 end
  81.     foreach f $flist(unseen) {
  82.     $flist(listbox).unseen insert end $f
  83.     }
  84. }
  85. proc FlistTraceUnvisited {args} {
  86.     global flist
  87.     $flist(listbox).unvisited delete 0 end
  88.     foreach f $flist(unvisited) {
  89.     $flist(listbox).unvisited insert end $f
  90.     }
  91. }
  92.  
  93. ### Routines to find all folders, figure out which have nested folders, etc.
  94.  
  95. # This is commonly bound to the "Flist" button - reset the state
  96. # about folders.
  97.  
  98. proc Flist_Refresh {} {
  99.     global flist
  100.     FlistResetVars
  101.     FlistFindAllInner
  102.     Fdisp_Redisplay
  103.     Flist_FindUnseen 1
  104.     Folder_FindShared
  105.     Inc_PresortFinish
  106. }
  107.  
  108. proc Flist_FindAllFolders {{force 0}} {
  109.     global flist mhProfile flistSubCache flistParents
  110.  
  111.     if ![info exists flist(cacheFile)] {
  112.     set flist(cacheFile) $mhProfile(path)/.folders
  113.     }
  114.     if {$force || ![file readable $flist(cacheFile)] ||
  115.         [file size $flist(cacheFile)] == 0} {
  116.     FlistFindAllInner
  117.     } elseif {![info exists flist(allfolders)]||
  118.         [file mtime $flist(cacheFile)] > $flist(cacheFileMtime)} {
  119.     set in [open $flist(cacheFile)]
  120.     set flist(allfolders) [FlistSort [split [read $in] \n]]
  121.     close $in
  122.     set flist(cacheFileMtime) [file mtime $flist(cacheFile)]
  123.     FlistSubFoldersInit
  124.     BgAction FlistUnseenFoldersInit FlistUnseenFoldersInit
  125.     }
  126.     Folder_FindShared
  127. }
  128. proc FlistFindAllInner {} {
  129.     global flist flistSubCache flistParents mhProfile
  130.     catch {destroy .scanning}
  131.     Widget_Toplevel .scanning "Scanning..."
  132.     Widget_Message .scanning msg -cursor watch -text "
  133. Scanning for nested folders.
  134. (folders -all -fast -recurse)
  135.  
  136. The results are cached in
  137. $mhProfile(path)/.folders
  138. so you won't have to wait like
  139. this until you press the Folders
  140. button to update the folder set.
  141.  
  142. Please wait...
  143. "
  144.     Exmh_Status "Scanning for nested folders ..." warn
  145.     update
  146.     set bogus [catch {exec folders -all -fast -recurse} raw]
  147.     set raw [split $raw \n]
  148.     if {$bogus} {
  149.     set ix [lsearch -glob $raw "* * *"]
  150.     if {$ix >= 0} {
  151.         set msg [lindex $raw $ix]
  152.         .scanning.msg config -text $msg
  153.         Exmh_Status $msg
  154.         catch {puts stderr $raw}
  155.         update
  156.         after 1000
  157.         set raw [lreplace $raw $ix $ix]
  158.     } else {
  159.         Exmh_Status "Folders error report on stderr"
  160.         catch {puts stderr $raw}
  161.     }
  162.     }
  163.  
  164.     set flist(allfolders) [FlistSort $raw]
  165.     FlistSubFoldersInit
  166.     BgAction FlistUnseenFoldersInit FlistUnseenFoldersInit
  167.     FlistCacheFolderList
  168.     destroy .scanning
  169. }
  170. proc Flist_AddFolder { folder } {
  171.     global flist
  172.     if {[lsearch $flist(allfolders) $folder] >= 0} {
  173.     Exmh_Debug "Flist_AddFolder already has $folder"
  174.     } else {
  175.     lappend flist(allfolders) $folder
  176.     }
  177.     set flist(allfolders) [FlistSort $flist(allfolders)]
  178.     FlistSubFoldersInit
  179.     BgAction FlistUnseenFoldersInit FlistUnseenFoldersInit
  180.     FlistCacheFolderList
  181.     Fdisp_Redisplay
  182. }
  183. proc Flist_DelFolder { folder } {
  184.     global flist
  185.     set ix [lsearch $flist(allfolders) $folder]
  186.     if {$ix < 0} {
  187.     return
  188.     }
  189.     set flist(allfolders) [FlistSort [lreplace $flist(allfolders) $ix $ix]]
  190.     FlistSubFoldersInit
  191.     BgAction FlistUnseenFoldersInit FlistUnseenFoldersInit
  192.     FlistCacheFolderList
  193.     Fdisp_Redisplay
  194. }
  195. proc FlistCacheFolderList {} {
  196.     global flist
  197.     if [catch {open $flist(cacheFile) w} out] {
  198.     Exmh_Status "Cannot cache folder list: $out" red
  199.     } else {
  200.     foreach f $flist(allfolders) {
  201.         puts $out $f
  202.     }
  203.     close $out
  204.     set flist(cacheFileMtime) [file mtime $flist(cacheFile)]
  205.     }
  206. }
  207. proc FlistUnseenFoldersInit {} {
  208.     global flist mhProfile
  209.  
  210.     set flist(unseenfolders) {}
  211.     foreach f $flist(allfolders) {
  212.         foreach pat $mhProfile(folder-unseen) {
  213.         if {[string compare ! [string range $pat 0 0]] == 0} {
  214.         if [string match [string range $pat 1 end] $f] {
  215.             break
  216.         }
  217.         }
  218.             if [string match $pat $f] {
  219.                 lappend flist(unseenfolders) $f
  220.                 break
  221.             }
  222.         }
  223.     }
  224. }
  225. proc FlistSubFoldersInit {} {
  226.     global flist subFolders flistSubCache flistParents
  227.  
  228.     catch {unset subFolders}    ;# Map from name to list of children
  229.     catch {unset flistSubCache}
  230.     catch {unset flistParents}
  231.     foreach f $flist(allfolders) {
  232.     append subFolders([file dirname $f]) "$f "
  233.     }
  234. }
  235. proc Flist_SubFolders {{folder .}} {
  236.     global subFolders
  237.  
  238.     return [info exists subFolders($folder)]
  239. }
  240. proc Flist_FolderSet { {subfolder .} } {
  241.     #  Find all folders at a given level in the folder hierarchy
  242.     global flist flistSubCache
  243.     if [info exists flistSubCache($subfolder)] {
  244.     return $flistSubCache($subfolder)
  245.     }
  246.     foreach f $flist(allfolders) {
  247.     set parent [file dirname $f]
  248.     if {$subfolder == $parent || $subfolder == $f} {
  249.         lappend result $f
  250.     }
  251.     }
  252.     if ![info exists result] {
  253.     return {}
  254.     } else {
  255.     set flistSubCache($subfolder) $result
  256.     return $result
  257.     }
  258. }
  259.  
  260. # The routines below here manage the unseen sequence state per folder.
  261.  
  262. proc FlistSeq { folder sequence } {
  263.     global mhProfile
  264.     # Explode a sequence into a list of message numbers
  265.     set seq {}
  266.     set rseq {}
  267.     foreach range [split [string trim $sequence]] {
  268.     set parts [split [string trim $range] -]
  269.     if {[llength $parts] == 1} {
  270.         lappend seq $parts
  271.         set rseq [concat $parts $rseq]
  272.     } else {
  273.         for {set m [lindex $parts 0]} {$m <= [lindex $parts 1]} {incr m} {
  274.         lappend seq $m
  275.         set rseq [concat $m $rseq]
  276.         }
  277.     }
  278.     }
  279.     # Hack to weed out unseen sequence numbers for messages that don't exist
  280.     foreach m $rseq {
  281.     if ![file exists $mhProfile(path)/$folder/$m] {
  282.         Exmh_Debug $mhProfile(path)/$folder/$m not found
  283.         set ix [lsearch $seq $m]
  284.         set seq [lreplace $seq $ix $ix]
  285.     } else {
  286.         # Real hack
  287.         break
  288.     }
  289.     }
  290.     return $seq
  291. }
  292.  
  293. # Reset the cached state about unseen messages because the user
  294. # has just packed, sorted, or threaded the folder.
  295. # This should be followed shortly by a call to Flist_UnseenMsgs
  296. #
  297. # Don't call gratitiously because it confuses the exmhunseen window.
  298.  
  299. proc Flist_ForgetUnseen {folder} {
  300.     global flist
  301.     set flist(newseq,$folder) {}
  302.     if {[info exists flist(new,$folder)]} {
  303.     set flist(newMsgs) [expr $flist(newMsgs) - $flist(new,$folder)]
  304.     }
  305.     set flist(new,$folder) 0
  306.     set ix [lsearch $flist(unseen) $folder]
  307.     if {$ix >= 0} {
  308.     set flist(unseen) [lreplace $flist(unseen) $ix $ix]
  309.     }
  310. }
  311.  
  312. # Add unseen messages to the list for a given folder.
  313. # This has to be careful about already known unseen messages
  314. # and messages that have been read but not committed as read.
  315. proc Flist_AddUnseen {folder seq} {
  316.     global flist exmh
  317.  
  318.     # Check overlap with already seen msgs and unseen messages already known
  319.     if [info exists flist(newseq,$folder)] {
  320.     if [info exists flist(new,$folder)] {
  321.         set new $flist(new,$folder)
  322.     } else {
  323.         set new 0
  324.     }
  325.     } else {
  326.     set flist(newseq,$folder) {}
  327.     set new 0
  328.     }
  329.     if {[string compare $folder $exmh(folder)] == 0} {
  330.     set known [concat [Msg_Seen] $flist(newseq,$folder)]
  331.     } else {
  332.     set known $flist(newseq,$folder)
  333.     }
  334.     # Subtract elements of $known from $seq
  335.     if {[llength $known] > [llength $seq]} {
  336.     set nseq {}
  337.     foreach id $seq {
  338.         if {[lsearch $known $id] < 0} {
  339.         lappend nseq $id
  340.         }
  341.     }
  342.     set seq $nseq
  343.     } else {
  344.     foreach id $known  {
  345.         set ix [lsearch $seq $id]
  346.         if {$ix >= 0} {
  347.         set seq [lreplace $seq $ix $ix]
  348.         }
  349.     }
  350.     }
  351.     set num [llength $seq]
  352.     if {$num <= 0} {
  353.     return
  354.     }
  355.     incr flist(newMsgs) $num
  356.     set flist(new,$folder) [expr $new + $num]
  357.     set flist(newseq,$folder) [concat $flist(newseq,$folder) $seq]
  358.     if {[lsearch $flist(unseen) $folder] < 0} {
  359.     lappend flist(unseen) $folder
  360.     }
  361.     if {[string compare $folder $exmh(folder)] != 0 &&
  362.     [lsearch $flist(unvisited) $folder] < 0} {
  363.     lappend flist(unvisitedNext) $folder
  364.     }
  365.     Fdisp_HighlightUnseen $folder
  366.     if 0 {
  367.     # This line of code causes doubling of messages in the scan listing.
  368.     # don't do it
  369.     if {[string compare $exmh(folder) $folder] == 0} {
  370.       Scan_Folder $folder
  371.     }
  372.     }
  373. }
  374. proc Flist_Done {} {
  375.     global flist exmh
  376.  
  377.     Exmh_Debug Flist_Done
  378.     if {$flist(newMsgs) > 0} {
  379.     if {$flist(newMsgs) == 1} {set msg "msg"} else {set msg "msgs"}
  380.     if {[llength $flist(unseen)] == 1} {set f "folder"} else {set f "folders"}
  381.     Exmh_Status "$flist(newMsgs) unread $msg in [llength $flist(unseen)] $f" blue
  382.     if ![info exists flist(lastNewMsgs)] {
  383.         set flist(lastNewMsgs) 0
  384.     }
  385.     set delta [expr {$flist(newMsgs) - $flist(lastNewMsgs)}]
  386.     if {$delta > 0} {
  387.         Flag_NewMail
  388.         Sound_Feedback $delta
  389.     }
  390.     } else {
  391.     set flist(newMsgs) 0
  392.     Flag_NoUnseen
  393.     Exmh_Status "No unread msgs" blue
  394.     }
  395.     set flist(lastNewMsgs) $flist(newMsgs)
  396.     set flist(unvisited) [FlistSort $flist(unvisitedNext)]
  397.     set flist(active) 0
  398. }
  399.  
  400.  
  401. # Call Flist_UnseenUpdate from external sorting programs after
  402. # they add messages to a folder
  403.  
  404. proc Flist_UnseenUpdate { folder } {
  405.     global exmh flist
  406.     Flist_ResetUnseen $folder
  407.     Flist_UnseenMsgs $folder
  408.     if {[string compare $folder $exmh(folder)] == 0} {
  409.     Scan_FolderUpdate $folder
  410.     }
  411.     if {[lsearch $flist(unvisited) $folder] < 0} {
  412.     lappend flist(unvisited) $folder
  413.     set flist(unvisitedNext) $flist(unvisited)
  414.     }
  415.     # This wiggles the flag and sorts flist(unvisited)
  416.     Flist_Done
  417. }
  418. proc Flist_ResetUnseen { folder } {
  419.     global flist
  420.     if [Flist_NumUnseen $folder] {
  421.     incr flist(newMsgs) -$flist(new,$folder)
  422.     set flist(newseq,$folder) {}
  423.     set flist(new,$folder) 0
  424.     }
  425. }
  426. proc Flist_UnseenMsgs { folder } {
  427.     global flist
  428.     Flist_AddUnseen $folder [Mh_Unseen $folder]
  429.     return $flist(newseq,$folder)
  430. }
  431. proc Flist_NumUnseen { folder } {
  432.     global flist
  433.     if [info exists flist(new,$folder)] {
  434.     return $flist(new,$folder)
  435.     } else {
  436.     return 0
  437.     }
  438. }
  439. proc Flist_UnseenFolders {} {
  440.     global flist
  441.     return $flist(unseen)
  442. }
  443.  
  444. # Flist enumerates folders that have unseen messages.
  445. proc Flist_FindUnseen {{reset 0}} {
  446.     Exmh_Debug Flist_FindUnseen end [time [list FlistFindUnseen $reset]]
  447. }
  448.  
  449. proc FlistFindStart {reset} {
  450.     global flist
  451.     if ![info exists flist(active)] {
  452.     set flist(active) 0
  453.     }
  454.     Exmh_Debug FlistFindStart reset=$reset active=$flist(active)
  455.     if {$flist(active)} {
  456.     return 0
  457.     }
  458.     set flist(active) 1
  459.     if {$reset} {
  460.     Fdisp_ClearHighlights
  461.     FlistResetVars
  462.     }
  463.     return 1
  464. }
  465. proc FlistFindUnseen {reset} {
  466.     global mhProfile flist curFolder
  467.     Exmh_Debug FlistFindUnseen reset=$reset
  468.     if {![BgRPC FlistFindStart $reset]} {
  469.     # Flist active
  470.     return
  471.     }
  472.     if {[catch {
  473.     FlistGetContext
  474.     set result {}
  475.     set keep {}
  476.     foreach f $flist(unseenfolders) {
  477.         set hit 0
  478.         foreach line $flist(context) {
  479.         set line [split $line]
  480.         set key [lindex $line 0]
  481.         if {$key == "atr-$mhProfile(unseen-sequence)-$mhProfile(path)/$f:"} {
  482.             set seq [lindex [split $line :] 1]
  483.             BgRPC Flist_AddUnseen $f [FlistSeq $f $seq]
  484.             set hit 1
  485.             break
  486.         }
  487.         }
  488.         if {! $hit} {
  489.         set path $mhProfile(path)/$f/$mhProfile(mh-sequences)
  490.         if {![file exists $path] ||
  491.             ([info exists flist(mtime,$f)] &&
  492.              ([file mtime $path] <= $flist(mtime,$f)))} {
  493.             # No state to report
  494.         } else {
  495.             if {[catch {open $path} in] == 0} {
  496.             set se \n[read $in]
  497.             if [regexp \n$mhProfile(unseen-sequence):\[^\n\]*\n $se line] {
  498.                 set seq [lindex [split $line :\n] 2]
  499.                 BgRPC Flist_AddUnseen $f [FlistSeq $f $seq]
  500.             }
  501.             close $in
  502.             set flist(mtime,$f) [file mtime $path]
  503.             }
  504.         }
  505.         }
  506.     }
  507.     } err]} {
  508.     # An error here is most likely a flakey NFS connection
  509.     # It is important to trap this so we can mark the
  510.     # flist action as "Done" below.  Otherwise, we'll stop
  511.     # looking for new messages.
  512.     Exmh_Debug "FlistFindUnseen: $err"
  513.     }
  514.     BgRPC Flist_Done
  515. }
  516. proc FlistGetContext {} {
  517.     global flist mhProfile
  518.     if {$flist(contextMtime) < [file mtime $mhProfile(context)]} {
  519.     if {[catch {open $mhProfile(context)} in] == 0} {
  520.         set flist(context) [split [read $in] \n]
  521.         set flist(contextMtime) [file mtime $mhProfile(context)]
  522.         close $in
  523.     }
  524.     }
  525. }
  526. proc Flist_MsgSeen { msgid } {
  527.     global flist exmh
  528.     if [info exists flist(newseq,$exmh(folder))] {
  529.     set ix [lsearch $flist(newseq,$exmh(folder)) $msgid]
  530.     if {$ix >= 0} {
  531.         set flist(newseq,$exmh(folder)) \
  532.         [lreplace $flist(newseq,$exmh(folder)) $ix $ix]
  533.         incr flist(new,$exmh(folder)) -1
  534.         incr flist(newMsgs) -1
  535.         set flist(lastNewMsgs) $flist(newMsgs)
  536.         if {$flist(new,$exmh(folder)) == 0} {
  537.         FlistUnseenFolder $exmh(folder)
  538.         }
  539.         if {$flist(newMsgs) <  0} {
  540.         Exmh_Status "$flist(newMsgs) unseen!"
  541.         set flist(newMsgs) 0
  542.         }
  543.     }
  544.     }
  545. }
  546. proc Flist_SeenAll { folder } {
  547.     FlistUnseenFolder $folder
  548. }
  549. proc FlistUnseenFolder { folder } {
  550.     global flist
  551.     Exmh_Debug FlistUnseenFolder $folder
  552.     catch {unset flist(new,$folder)}
  553.     catch {unset flist(newseq,$folder)}
  554.     Fdisp_UnHighlightUnseen $folder
  555.     set ix [lsearch $flist(unseen) $folder]
  556.     if {$ix >= 0} {
  557.     set flist(unseen) [lreplace $flist(unseen) $ix $ix]
  558.     if {[llength $flist(unseen)] == 0} {
  559.         Flag_NoUnseen
  560.     }
  561.     }
  562.     set ix [lsearch $flist(unvisited) $folder]
  563.     if {$ix >= 0} {
  564.     set flist(unvisited) [lreplace $flist(unvisited) $ix $ix]
  565.     }
  566.     set ix [lsearch $flist(unvisitedNext) $folder]
  567.     if {$ix >= 0} {
  568.     set flist(unvisitedNext) [lreplace $flist(unvisitedNext) $ix $ix]
  569.     }
  570. }
  571.  
  572. proc FlistSort { dirlist } {
  573.     # Order the folder list according to a pattern template.
  574.     # Patterns early in the list have higher priority.
  575.  
  576.     # Hack to check against mh-e .folders file
  577.     if [regexp {\("\+} $dirlist] {
  578.     global flist
  579.     error \
  580. "Conflict with mh-e $flist(cacheFile).  Either remove it or override its name.
  581. The mh-e variable is mh-folder-list-filename.
  582. For exmh, set the variable flist(cacheFile) to another file.
  583. Add this to your user.tcl file (see exmh-custom man page for details).
  584. set flist(cacheFile) /usr/joe/Mail/.exmhfolders
  585. "
  586.     }
  587.     global mhProfile
  588.     set patterns $mhProfile(folder-order)
  589.  
  590.     set max [llength $patterns]
  591.     set dirlist [lsort $dirlist]
  592.     foreach f $dirlist {
  593.     set patLength($f) 0
  594.     }
  595.     foreach f $dirlist {
  596.     set hit 0
  597.     for {set pri 0} {$pri < $max} {incr pri} {
  598.         set pat [lindex $patterns $pri]
  599.         set patLen [string length $pat]
  600.         if {$patLen > $patLength($f)} {
  601.         if [string match $pat $f] {
  602.             set priority($f) $pri
  603.             set patLength($f) $patLen
  604.             set hit 1
  605.         }
  606.         }
  607.     }
  608.     if {! $hit} {
  609.         set priority($f) $max
  610.     }
  611.     }
  612.     foreach f $dirlist {
  613.     set hide 0
  614.     if {$f == {}} {
  615.         set hide 1
  616.     }
  617.     foreach pat $mhProfile(folder-ignore) {
  618.         if [string match $pat $f] {
  619.         set hide 1
  620.         break
  621.         }
  622.     }
  623.     if {! $hide} {
  624.         lappend pset($priority($f)) $f
  625.     }
  626.     }
  627.     set result ""
  628.     for {set pri 0} {$pri <= $max} {incr pri} {
  629.     if [info exists pset($pri)] {
  630.         append result $pset($pri) " "
  631.     }
  632.     }
  633.     return $result
  634. }
  635.  
  636. proc Flist_NextUnseen { } {
  637.     # Return the next folder in Folder-Order that has unseen messages
  638.     global flist exmh
  639.  
  640.     foreach f $flist(unvisited) {
  641.     if {[string compare $f $exmh(folder)] != 0} {
  642.         return $f
  643.     }
  644.     }
  645.     foreach f $flist(unseen) {
  646.     if {[string compare $f $exmh(folder)] != 0} {
  647.         return $f
  648.     }
  649.     }
  650.     set first [lindex $flist(allfolders) 0]
  651.     if {$flist(cycleBack) && [string compare $first $exmh(folder)]} {
  652.     return $first
  653.     } else {
  654.     return {}
  655.     }
  656. }
  657. proc Flist_Visited { f } {
  658.     global flist
  659.     set ix [lsearch $flist(unvisited) $f]
  660.     if {$ix >= 0} {
  661.     set flist(unvisited) [lreplace $flist(unvisited) $ix $ix]
  662.     }
  663. }
  664.